#include "user_include.h"

#ifdef __MEMORY_POOL_H__

#define MEMORY_POOL_SIZE 1024         // 定义内存池大小，可以根据需要调整
#define ALIGN4(x) (((x) + 3) & ~0x03) // 四字节对齐

typedef struct block_meta
{
    size_t size;             // 当前内存块的大小
    struct block_meta *next; // 指向下一个内存块的指针
    struct block_meta *prev; // 指向前一个内存块的指针
    u8 free;                 // 标志位，表示该块是否空闲
} block_meta;

static void Init_Memory_Pool(void);
static block_meta *Find_Free_Block(size_t size);
static void Split_Block(block_meta *fitting_slot, size_t size);
static void Merge_Free_Blocks(block_meta *block);

// 内存池和自由链表
static u8 memory_pool[MEMORY_POOL_SIZE] __attribute__((aligned(4)));
static block_meta *free_list = (block_meta *)memory_pool;
static int memory_init = 0;

// 内存使用信息
size_t memory_num = 0; // 追踪当前分配的内存块数量
u16 memory_use = 0;    // 当前使用的内存块大小

// 初始化内存池
static void Init_Memory_Pool(void)
{
    free_list->size = MEMORY_POOL_SIZE - sizeof(block_meta);
    free_list->free = 1;
    free_list->next = NULL;
    free_list->prev = NULL;
}

// 查找第一个适合的空闲块
static block_meta *Find_Free_Block(size_t size)
{
    block_meta *current = free_list;
    while (current && !(current->free && current->size >= size))
    {
        current = current->next;
    }
    return current;
}

// 分割块
static void Split_Block(block_meta *fitting_slot, size_t size)
{
    if (fitting_slot->size >= size + sizeof(block_meta) + 4)
    { // 确保剩余空间足够
        block_meta *new_block = (block_meta *)((uint8_t *)fitting_slot + sizeof(block_meta) + size);
        new_block->size = fitting_slot->size - size - sizeof(block_meta);
        new_block->free = 1;
        new_block->next = fitting_slot->next;
        new_block->prev = fitting_slot; // 设置新块的 prev 指针

        if (fitting_slot->next)
        {
            fitting_slot->next->prev = new_block; // 更新下一个块的 prev 指针
        }

        fitting_slot->size = size;
        fitting_slot->free = 0;
        fitting_slot->next = new_block;
    }
    else
    {
        fitting_slot->free = 0;
    }
}

// 合并相邻的空闲块
static void Merge_Free_Blocks(block_meta *block)
{
    // 尝试与下一块合并
    if (block->next && block->next->free)
    {
        block->size += sizeof(block_meta) + block->next->size;
        block->next = block->next->next;
        if (block->next)
        {
            block->next->prev = block;
        }
    }

    // 尝试与前一块合并
    if (block->prev && block->prev->free)
    {
        block->prev->size += sizeof(block_meta) + block->size;
        block->prev->next = block->next;
        if (block->next)
        {
            block->next->prev = block->prev;
        }
    }
}

// 自定义 malloc 实现
void *My_Malloc(size_t size)
{
    block_meta *block;
    if (size <= 0)
        return NULL;

    size = ALIGN4(size);
    if (!memory_init)
    {
        // 尚未初始化，初始化内存池
        Init_Memory_Pool();
        memory_init = 1;
    }

    block = Find_Free_Block(size);
    if (block)
    {
        // 找到适合的块
        Split_Block(block, size);
        memset(block + 1, 0, size);                // 正确初始化分配的内存
        memory_num++;                              // 申请的内存数+1
        memory_use += (size + sizeof(block_meta)); // 申请的内存大小
        return (void *)(block + 1);                // 返回数据部分
    }
    else
    {
        return NULL; // 内存池已满，没有足够的空间
    }
}

// 自定义 free 实现
void My_Free(void *ptr)
{
    if (!ptr)
        return;

    // 确保 ptr 位于内存池范围内
    block_meta *block = (block_meta *)ptr - 1;

    // 防止重复释放
    if (block->free)
        return; // 已经被释放，忽略或处理错误

    block->free = 1;
    memory_num--;                                     // 申请的内存数-1
    memory_use -= (block->size + sizeof(block_meta)); // 申请的内存大小

    // 尝试合并空闲块
    Merge_Free_Blocks(block);
}

#endif